from rest_framework import serializers

from apps.goods.models import SKU
from apps.users.models import User, Address
from django_redis import get_redis_connection


# 注册序列化器
class RegisterUserSerializer(serializers.ModelSerializer):
    password2 = serializers.CharField(min_length=8, max_length=20, write_only=True, label="确认密码")
    sms_code = serializers.CharField(write_only=True, label='短信验证码')
    allow = serializers.CharField(write_only=True, label='协议')

    class Meta:
        # 指定模型类
        model = User
        # 指定哪些字段
        fields = ["id", 'username', 'password', 'password2', 'mobile', 'sms_code', 'allow']
        # 添加额外约束
        extra_kwargs = {
            "password": {
                "write_only": True
            }
        }
        # 添加额外只读字段
        read_only_fields = ["id"]

    # 校验是否允许协议
    def validate_allow(self, value):
        if not value:
            raise serializers.ValidationError("请同意允许协议")

        return value

    # 多字段校验
    def validate(self, attrs):
        # 获取数据
        sms_code = attrs.get("sms_code")
        mobile = attrs.get("mobile")
        password = attrs.get("password")
        password2 = attrs.get("password2")

        # 获取redis对象
        redis_connection = get_redis_connection("code")
        # 获取redis的短信验证码
        redis_sms_code = redis_connection.get("sms_code_%s" % mobile)

        # 判断短信验证码是否过期
        if not redis_sms_code:
            raise serializers.ValidationError("短信验证码过期")
        # 判断用户填写的短信验证码是否正确
        if sms_code != redis_sms_code.decode():
            raise serializers.ValidationError("短信验证码填写错误")

        # 校验密码是否相等
        if password != password2:
            raise serializers.ValidationError("两次密码不一致")

        return attrs

    def create(self, validated_data):
        # 去除不存入数据库的字段
        del validated_data['password2']
        del validated_data['sms_code']
        del validated_data['allow']

        # 调用父类的create方法，创建用户实例
        user = super().create(validated_data)

        # 将存入数据库的密码设置为密文
        user.set_password(validated_data['password'])
        user.save()

        # 设置JWT
        from rest_framework_jwt.settings import api_settings
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return user


# 用户中心首页展示序列化器
class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", 'username', 'mobile', 'email', 'email_active']


# 收货地址序列化器
class AddressSerializer(serializers.ModelSerializer):
    #序列化时输出名字，不是id
    province=serializers.StringRelatedField(read_only=True)
    city=serializers.StringRelatedField(read_only=True)
    district=serializers.StringRelatedField(read_only=True)
    # user_id=serializers.StringRelatedField()

    #因为前端带过来的的是province_id，所以要重写
    province_id = serializers.IntegerField(label="省id")
    city_id = serializers.IntegerField(label="市id")
    district_id = serializers.IntegerField(label="区id")

    #数据库写入的时候需要加上userid
    user_id=serializers.IntegerField(label="绑定的id")
    class Meta:
        model = Address
        #排除的字段
        exclude = ["user", "is_deleted", "create_time", "update_time"]

    # def create(self, validated_data):
    #     validated_data["user"] = self.context["request"].user
    #     return super(AddressSerializer, self).create(validated_data)

#用户浏览记录序列化器
class UserBrowerHistorySerializer(serializers.Serializer):
    sku_id=serializers.IntegerField(min_value=1,label="商品编号")

    def validate_sku_id(self,value):
        #判断商品编号是否存在
        try:
            SKU.objects.get(id=value)
        except Exception:
            raise serializers.ValidationError("商品编号不存在")

        return value


    def create(self, validated_data):
        #得到redis对象
        redis_conn=get_redis_connection("history")

        #获取用户对象
        user=self.context['request'].user

        #获取sku_id
        sku_id=validated_data.get("sku_id")

        #去重
        redis_conn.lrem("history_%s" %user.id,0,sku_id)

        #添加到redis数据库
        redis_conn.lpush("history_%s" %user.id,sku_id)

        #截取前5条浏览记录
        redis_conn.ltrim("history_%s" %user.id,0,4)

        return validated_data